package model

import (
	"fmt"
	"github.com/liushuochen/gotable"
	"gorm.io/gorm"
)

type Bastion struct {
	ConnectIP        string `gorm:"primaryKey"`
	PrivateIP        string
	PublicIP         string
	SSHPort          int    `gorm:"not null; default 22"`
	SSHUser          string `gorm:"not null; default 'proxy'"`
	SSHPassword      string
	SSHKeyFile       string
	SSHKeyPassphrase string
	Vendor           string
	Region           string
}

func (b Bastion) CheckExist() (bool, error) {
	var c int64
	if err := DB.Where("connect_ip = ?", b.ConnectIP).Find(&Bastion{}).Count(&c).Error; err != nil {
		return false, err
	}
	return c > 0, nil
}

func (b Bastion) Insert() error {
	return DB.Create(&b).Error
}

func (b Bastion) Update() error {
	return DB.Save(&b).Error
}

func (b Bastion) InsertOrUpdate() error {
	exist, err := b.CheckExist()
	if err != nil {
		return err
	}
	if exist {
		return b.Update()
	}
	return b.Insert()
}

func (b Bastion) Delete() error {
	return DB.Delete(&b).Error
}

func QueryBastionsForPrint(condition map[string]string) (string, error) {
	bastionList, err := QueryBastionsByConditions(condition)
	if err != nil {
		return "", err
	}
	var m = make(map[string]string, 2)
	tb, _ := gotable.Create("no", "vendor", "region", "connect_ip", "private_ip", "public_ip", "ssh_user", "ssh_port", "ssh_key_file")
	no := 1
	for _, bastion := range *bastionList {
		m = map[string]string{
			"no":           fmt.Sprintf("%d", no),
			"vendor":       bastion.Vendor,
			"region":       bastion.Region,
			"connect_ip":   bastion.ConnectIP,
			"private_ip":   bastion.PrivateIP,
			"public_ip":    bastion.PublicIP,
			"ssh_user":     bastion.SSHUser,
			"ssh_port":     fmt.Sprintf("%d", bastion.SSHPort),
			"ssh_key_file": bastion.SSHKeyFile,
		}
		if err := tb.AddRow(m); err != nil {
			return "", err
		}
		no += 1
	}
	tb.OpenBorder()
	return tb.String(), nil
}

func QueryBastionsByConditions(condition map[string]string) (*[]Bastion, error) {
	bastionList := make([]Bastion, 0, 2)
	err := DB.Where(condition).Find(&bastionList).Error
	return &bastionList, err
}

func QueryBastionByCondition(condition map[string]string) (*Bastion, error) {
	bastion := Bastion{}
	err := DB.Where(condition).First(&bastion).Error
	if err == gorm.ErrRecordNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &bastion, err
}

func DeleteBastionsByCondition(condition map[string]string) error {
	return DB.Where(condition).Delete(&Bastion{}).Error
}
